﻿using System;
using System.Collections.Generic;
using System.Linq;

namespace Cms.Domain
{
    [Serializable]
    public class MasterTemplate : Template
    {
        private IList<MasterTemplateStylesheet> _associatedStylesheets;
        private IList<MasterTemplateContentLink> _content;
        private IList<DetailTemplate> _defaultDetailTemplates;
        private IList<string> _areas;
        private IList<string> _pageAreas;

        public MasterTemplate()
        {
            _areas = new List<string>();
            _pageAreas = new List<string>();
            _associatedStylesheets = new List<MasterTemplateStylesheet>();
            _defaultDetailTemplates = new List<DetailTemplate>();
            _content = new List<MasterTemplateContentLink>();
        }

        public virtual IList<string> Areas
        {
            get { return _areas; }
            set { _areas = value; }
        }

        public virtual IList<string> PageAreas
        {
            get { return _pageAreas; }
            set { _pageAreas = value; }
        }

        public virtual IList<MasterTemplateStylesheet> AssociatedStylesheets
        {
            get { return _associatedStylesheets; }
            set { _associatedStylesheets = value; }
        }
        
        public virtual IList<DetailTemplate> DefaultDetailTemplates
        {
            get { return _defaultDetailTemplates; }
            set { _defaultDetailTemplates = value; }
        }
        
        public virtual IList<MasterTemplateContentLink> Content
        {
            get { return _content; }
            set { _content = value; }
        }
        
        public override string GetPublishedContentHtml(string areaID, int localeID)
        {
            foreach (MasterTemplateContentLink mtl in _content.Where(mtl => mtl.AreaID == areaID))
            {
                return mtl.Content.GetPublishedHtml(localeID);
            }
            return string.Empty;
        }

        public override string GetPublishedContentTitle(string areaID, int localeID)
        {
            foreach (MasterTemplateContentLink mtl in _content.Where(mtl => mtl.AreaID == areaID))
            {
                return mtl.Content.GetPublishedTitle(localeID);
            }
            return string.Empty;
        }
        
        public override string GetContentHtml(string areaID, int localeID, string timestamp)
        {
            foreach (MasterTemplateContentLink mtl in _content.Where(mtl => mtl.AreaID == areaID))
            {
                return mtl.Content.GetHtml(localeID, timestamp);
            }
            return string.Empty;
        }
        
        public override string GetContentTitle(string areaID, int localeID, string timestamp)
        {
            foreach (MasterTemplateContentLink mtl in _content.Where(mtl => mtl.AreaID == areaID))
            {
                return mtl.Content.GetTitle(localeID, timestamp);
            }
            return string.Empty;
        }

        public virtual void RemoveStylesheet(Stylesheet stylesheet)
        {
            int i = 0;
            while (i < _associatedStylesheets.Count)
            {
                if (_associatedStylesheets[i].Stylesheet.ID == stylesheet.ID)
                {
                    _associatedStylesheets[i].Stylesheet.AssociatedMasterTemplates.Remove(_associatedStylesheets[i]);
                    _associatedStylesheets[i].Stylesheet = null;
                    _associatedStylesheets[i].MasterTemplate = null;
                    _associatedStylesheets.RemoveAt(i);
                    break;
                }
                else
                    i++;
            }
            for (i = 0; i < _associatedStylesheets.Count; i++)
                _associatedStylesheets[i].SortIndex = i;
        }
        
        public virtual IList<MasterTemplateStylesheet> GetAssociatedStylesheetsSorted()
        {
            var sortedAssociatedStylesheets = new List<MasterTemplateStylesheet>(_associatedStylesheets);
            sortedAssociatedStylesheets.Sort();
            _associatedStylesheets.Clear();
            foreach (MasterTemplateStylesheet mts in sortedAssociatedStylesheets)
                _associatedStylesheets.Add(mts);
            return sortedAssociatedStylesheets;
        }

        public virtual IList<Stylesheet> GetStylesheets()
        {
            IList<Stylesheet> used = new List<Stylesheet>();
            foreach (MasterTemplateStylesheet mts in GetAssociatedStylesheetsSorted())
                used.Add(mts.Stylesheet);
            return used;
        }
        
        public virtual IList<Stylesheet> GetUnusedStylesheets()
        {
            IList<Stylesheet> unused = new List<Stylesheet>();

            // Loop through all stylesheets for the site
            foreach (Stylesheet stylesheet in Site.Stylesheets)
            {
                bool isInUse = false;
                foreach (MasterTemplateStylesheet usedStylesheet in _associatedStylesheets)
                {
                    if (usedStylesheet.Stylesheet.ID == stylesheet.ID)
                    {
                        isInUse = true;
                        break;
                    }
                }
                if (!isInUse)
                    unused.Add(stylesheet);
            }
            return unused;
        }

        public virtual void AddStylesheet(Stylesheet stylesheet)
        {
            var mts = new MasterTemplateStylesheet
                          {
                              MasterTemplate = this,
                              Stylesheet = stylesheet,
                              SortIndex = _associatedStylesheets.Count
                          };
            _associatedStylesheets.Add(mts);
            stylesheet.AssociatedMasterTemplates.Add(mts);
        }

        public virtual void InsertStylesheet(int index, Stylesheet stylesheet)
        {
            var mts = new MasterTemplateStylesheet
                          {
                              MasterTemplate = this,
                              Stylesheet = stylesheet,
                              SortIndex = index
                          };
            _associatedStylesheets.Insert(index, mts);
            stylesheet.AssociatedMasterTemplates.Add(mts);
            for (int i = index + 1; i < _associatedStylesheets.Count; i++)
                _associatedStylesheets[i].SortIndex = i;
        }

        public override Content GetContent(string areaID)
        {
            return (from mtl in _content where mtl.AreaID == areaID select mtl.Content).FirstOrDefault();
        }
        
        public override void AddContentLink(string areaID, Content content)
        {
            IList<MasterTemplateContentLink> links =
                _content.Where(existingLink => existingLink.AreaID == areaID).ToList();
            foreach (MasterTemplateContentLink existingLink in links)
            {
                // Remove all versions associated with the old content from the sets
                foreach (var kvp in ContentSets)
                {
                    ContentSet set = kvp.Value;
                    IList<ContentTranslationVersion> removableVersions = new List<ContentTranslationVersion>();
                    foreach (ContentTranslationVersion version in set.TranslationVersions)
                    {
                        if (version.Translation.Content.ID == existingLink.Content.ID)
                            removableVersions.Add(version);
                    }
                    foreach (ContentTranslationVersion version in removableVersions)
                        set.TranslationVersions.Remove(version);
                }
                _content.Remove(existingLink);
            }
            var link = new MasterTemplateContentLink
                           {
                               Content = content,
                               AreaID = areaID,
                               MasterTemplate = this
                           };
            _content.Add(link);
            content.MasterTemplates.Add(link);
        }

        public override void PublishContentVersion(int localeID, ContentTranslationVersion ctv)
        {
            if (ContentSets.ContainsKey(localeID))
                ContentSets[localeID].PublishedVersion = ctv;
            foreach (ContentTranslation translation in from masterTemplateLink in _content
                                                       where
                                                           masterTemplateLink.Content.Translations.ContainsKey(localeID)
                                                       select masterTemplateLink.Content.Translations[localeID])
            {
                translation.PublishVersion(ctv.Timestamp);
            }
        }

        protected override ContentSet CreateContentSet(Locale locale)
        {
            return new MasterTemplateContentSet(this, locale);
        }
    }
}